//
//  DeviceMessage.m
//  integration_test
//
//  Created by mateng on 2024/2/19.
//

#import "DeviceMessage.h"
#import "StringUtils.h"
#import "AudioToolbox/AudioToolbox.h"
#import "Tools.h"
#import "DateUtils.h"

#define PATH                      @"device"
#define M_scanDevice              @"scanDevice"
#define M_cancelScan              @"cancelScan"
#define M_connect                 @"connect"
#define M_disconnect              @"disconnect"
#define M_getDeviceInfo           @"getDeviceInfo"
#define M_getBatteryInfo          @"getBatteryInfo"
#define M_getBondedDevices        @"getBondedDevices"
#define M_getDefaultConfiguration @"getDefaultConfiguration"
#define M_localNotify             @"localNotify"

#define STATE_DISCONNECTED        0
#define STATE_CONNECTING          1
#define STATE_CONNECTED           2

#define DISCONNECT_TYPE_NONE      0
#define DISCONNECT_TYPE_MANUAL    1
#define DISCONNECT_TYPE_ID_CHANGE 2
#define DISCONNECT_TYPE_RESET     3
#define DISCONNECT_TYPE_BOND      4
#define DISCONNECT_TYPE_UPGRADING 5

@interface DeviceMessage ()

@property (nonatomic, strong) NSTimer         *timerConnection;
@property (nonatomic, strong) NSString        *taskName;

@property (nonatomic, strong) UTEModelDevice  *currentModel;
@property (nonatomic, strong) NSMutableArray  *deviceArray;

@property (nonatomic, strong) NSString        *userId;
@property (nonatomic, strong) NSString        *address;
@property (nonatomic, assign) BOOL            fromQrcode;
@property (nonatomic, assign) NSInteger       disconnectType;
@property (nonatomic, assign) NSInteger       percent;
@property (nonatomic, assign) BOOL isPaired;

- (UTEModelDevice*) getDeviceModel:(NSString*) address;
- (BOOL)isValidDevice:(UTEModelDevice*) device;
- (void)notifyConnected;
- (BOOL)connectDevice;
- (void)pairDevice;
- (void)disconnectDevice:(NSInteger) type;
- (void)notifyDisconnectEvent:(NSInteger) type;

- (void)getDeviceInfo:(FlutterResult)result;
- (NSString*) getFullMacAddress:(NSString*)originalStr;

- (void)startTimerConnect:(NSTimeInterval) interval;
- (void)removeTimeoutTimer;
- (void)timeoutReport;

@end

@implementation DeviceMessage

- (id)initWithHandler:(UTEPedEventHandler *)handler
{
    self = [super initWithHandler:handler];
    if (self) {
        self.deviceArray = [NSMutableArray array];
        [UTEBluetoothMgr sharedInstance].isScanRepeat = YES;
        self.disconnectType = DISCONNECT_TYPE_NONE;
    }
    return self;
}

- (void)notificationListen {
    __weak typeof(self)weakSelf = self;
    
    // 1.41 监听设备相机状态 通知事件ID 为固定的 297
    [[UTEDeviceMgr sharedInstance] notifyCamera:^(UTECameraStatus status, NSInteger errorCode, NSDictionary *uteDict) {
        NSDictionary *data = [[NSDictionary alloc] initWithObjectsAndKeys:
                              PATH, KEY_PATH,
                              M_cameraControl, KEY_METHOD,
                              @(status), KEY_VALUE, nil];

        [weakSelf.eventHander publishEvent:data async:YES];
    }];
    
    
    // 11.1 监听手机防丢报警(手环查找手机) 通知事件ID 为固定的 2817
    [[UTEDeviceMgr sharedInstance] notifyFindMyPhoneNotifyReal:^(UTEFindWearStatus status, NSInteger errorCode, NSDictionary *uteDict) {
        if (status == UTEFindWearStatusOpen) {
            AudioServicesAddSystemSoundCompletion(kSystemSoundID_Vibrate, nil, nil, soundCompleteCallback, nil);
            AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
            AudioServicesAddSystemSoundCompletion(1304, nil, nil, soundCompleteCallback, nil);
            AudioServicesPlaySystemSound(1304);
        } else {
            AudioServicesRemoveSystemSoundCompletion(kSystemSoundID_Vibrate);
            AudioServicesRemoveSystemSoundCompletion(1304);
        }
    }];
    
    
    // 1.8 通知事件ID 为固定的 264
    [[UTEDeviceMgr sharedInstance] onNofityBattery:^(NSInteger battery, NSDictionary *uteDict) {
        NSDictionary *data = [[NSDictionary alloc] initWithObjectsAndKeys:
                              PATH, KEY_PATH,
                              weakSelf.address, KEY_ADDRESS,
                              M_getBatteryInfo, KEY_METHOD,
                              @(battery), KEY_BATTERY, nil];

        [weakSelf.eventHander publishEvent:data async:YES];
    }];
    
    [[UTEDeviceMgr sharedInstance].accountTool onNotifySelect:^(NSInteger result,NSDictionary *uteDict) {
        [weakSelf log: [NSString stringWithFormat:@"onNotifySelect result: %ld", result]];
        if (result == 0) {
            
        }
        else {
            [weakSelf disconnectDevice:DISCONNECT_TYPE_RESET];
        }
    }];
    
    [[UTEDeviceMgr sharedInstance].accountTool onNotifyAppPair:^(BOOL pair) {
        [weakSelf log: [NSString stringWithFormat:@"onNotifyAppPair %i", pair]];
    }];
    
    [[UTEDeviceMgr sharedInstance] onNotifyWeatherData:^(NSInteger errorCode, NSDictionary *uteDict) {
        if (errorCode == UTEDeviceErrorNil) {
            NSInteger weather = (NSInteger)uteDict[@"weather"];
            NSDictionary *data = [[NSDictionary alloc] initWithObjectsAndKeys:
                                  PATH, KEY_PATH,
                                  M_setFutureWeather, KEY_METHOD,
                                  @(weather), KEY_VALUE, nil];
            [weakSelf.eventHander publishEvent:data async:YES];
        }
    }];
}

- (NSString *)getPath {
    return @"device";
}

- (BOOL) methodCallConsumed:(NSString*)method params:(NSDictionary*)params result:(FlutterResult)result
{
    BOOL consumed = YES;
    if ([super methodCallConsumed:method params:params result:result])
        return YES;
    
    assert(method != nil);
    if ([method isEqualToString:M_scanDevice]) {
//        if (![UTEBluetoothMgr sharedInstance].connnectModel.isConnected) {
//            [[UTEBluetoothMgr sharedInstance] startScanDevices];
//            [self startTimerConnect];
//        }
        [[UTEBluetoothMgr sharedInstance] startScanDevices];
        [self startTimerConnect: 10.0];
        
        result(@YES);
    }
    else if([method isEqualToString:M_cancelScan]) {
        [[UTEBluetoothMgr sharedInstance] stopScanDevices];
        result(@YES);
    }
    else if([method isEqualToString:M_connect]) {
        BOOL success = NO;
        self.address = [params objectForKey:KEY_ADDRESS];
        self.fromQrcode = [[params objectForKey:KEY_FROM_QRCODE] boolValue];
        
        self.userId = [[SPHelper shareInstance] getObject:KEY_USERID defaultValue:@""];
        if (self.userId == nil || self.userId.length == 0) {
            self.userId = [params objectForKey:KEY_USERID];
            
            if (D_BUG) {
                [[SPHelper shareInstance] removeObject:KEY_USERID];
                self.userId = @"1234567890";
            }
            
            [[SPHelper shareInstance] putObject:self.userId value:KEY_USERID];
        }

        [self log:[NSString stringWithFormat:@"connect %@", self.address]];
        
        if (self.address != nil && ![UTEBluetoothMgr sharedInstance].connnectModel.isConnected) {
            if (self.fromQrcode) {
                [[UTEBluetoothMgr sharedInstance] startScanDevices];
                [self startTimerConnect: 20.0];
                result(@YES);
            }
            else {
                success = [self connectDevice];
                result(success ? @YES : @NO);
            }
        }
        else {
            result(@YES);
            [self performSelector:@selector(notifyConnected) withObject:nil afterDelay:3.0];
        }
    }
    else if([method isEqualToString:M_disconnect]) {
        NSNumber *enable = [params objectForKey:KEY_RESET];
        if ([enable boolValue]) {
            [[UTEDeviceMgr sharedInstance] resetFactory:(0) block:^(NSInteger errorCode, NSDictionary *uteDict) {
                NSLog(@"resetFactory result : %ld", errorCode);
            }];
        }
        [[DeviceHelper shareInstance] canelCheckTimer];
        [self disconnectDevice: DISCONNECT_TYPE_MANUAL];
        result(@YES);
    }
    else if([method isEqualToString:M_getDeviceInfo]) {
        [self getDeviceInfo:result];
    }
    else if([method isEqualToString:M_getBatteryInfo]) {
        [[UTEDeviceMgr sharedInstance] getBatteryInfo:^(NSInteger percent, NSInteger errorCode,NSDictionary *uteDict) {
            if (errorCode == UTEDeviceErrorNil) {
                result([NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithFormat:@"%ld", percent], @"percents", nil]);
            } else {
                result([NSDictionary dictionary]);
            }
        }];
    }
    else if([method isEqualToString:M_getBondedDevices]) {
        result([NSArray array]);
    }
    else if([method isEqualToString:M_getDefaultConfiguration]) {
        [[UTEDeviceMgr sharedInstance] getDefaultConfiguration:^(UTEModelDeviceInfoStatus1 *model, NSInteger errorCode, NSDictionary *uteDict) {
            if (errorCode == UTEDeviceErrorNil) {
                result(uteDict);
            }
            else {
                result([NSDictionary dictionary]);
            }
        }];
    }
    else if([method isEqualToString:M_setCameraStatus]) {
        NSNumber *paramStatus = [params objectForKey:KEY_STATUS];
        [[UTEDeviceMgr sharedInstance] setCameraStatus:[paramStatus intValue] block:^(NSInteger status, NSInteger errorCode, NSDictionary *uteDict) {
            result(errorCode == UTEDeviceErrorNil ? @YES : @NO);
        }];
    }
    else if([method isEqualToString:@"turnBluetooth"]) {
        [Tools openUrl: @"App-Prefs:root=Bluetooth"];
        result(@YES);
    }
    else {
        consumed = NO;
    }
    
    return consumed;
}

#pragma mark - get device info
- (void)getDeviceInfo:(FlutterResult)result
{
    __weak typeof(self)weakSelf = self;
    [[UTEDeviceMgr sharedInstance] getDeviceInfo:^(UTEModelDeviceElement *model, NSInteger errorCode, NSDictionary *uteDict) {
        if (errorCode == UTEDeviceErrorNil) {
            [[UTEDeviceMgr sharedInstance] getBatteryInfo:^(NSInteger percent, NSInteger errorCode,NSDictionary *uteDict) {

                NSMutableDictionary *di = [NSMutableDictionary dictionary];
                [di setObject:[UTEBluetoothMgr sharedInstance].connnectModel.name forKey:KEY_NAME];
                [di setObject:[weakSelf getFullMacAddress:[UTEBluetoothMgr sharedInstance].connnectModel.advertisementAddress] forKey:KEY_ADDRESS];
                [di setObject:model.deviceVersion forKey:@"deviceVersion"];
                [di setObject:model.systemVersion forKey:@"systemVersion"];
                NSString *deviceModel = @"";
                if (model.model != nil) {
                    deviceModel = model.model;
                }
                else if (model.certModel != nil) {
                    deviceModel = model.certModel;
                }
                [di setObject:deviceModel forKey:@"model"];
                if (errorCode == UTEDeviceErrorNil) {
                    [di setObject:[NSString stringWithFormat:@"%ld", percent] forKey:@"battery"];

                } else {
                    [di setObject:[NSString stringWithFormat:@"%ld", [UTEBluetoothMgr sharedInstance].connnectModel.battery] forKey:@"battery"];
                }
                
                [weakSelf setFirmwareInfo:di];
                result(di);
            }];

        } else {
            result([NSDictionary dictionary]);
        }
    }];
}

- (void)setFirmwareInfo:(NSMutableDictionary *)di {
    NSString *sv = [di objectForKey:@"systemVersion"];
    if (sv != nil) {
        NSArray *arr = [sv componentsSeparatedByString:@"V"];
        NSString *firmwareVersion = [NSString stringWithFormat:@"%@%@", @"V", [arr lastObject]];
        [di setObject:[arr firstObject] forKey:@"firmware"];
        [di setObject:firmwareVersion forKey:@"firmware_version"];
    }
}

- (NSString*) getFullMacAddress:(NSString*)originalStr {
    return [[StringUtils insertStringAll:originalStr insertStr:@":" position:2] uppercaseString];
}

#pragma mark - Timer Connect

- (void)startTimerConnect:(NSTimeInterval) interval
{
    [self removeTimeoutTimer];
    self.timerConnection = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(timeoutReport) userInfo:nil repeats:NO];
}

- (void)removeTimeoutTimer
{
    if (self.timerConnection) {
        [self.timerConnection invalidate];
    }
    self.timerConnection = nil;
}

- (void)timeoutReport
{
    [self removeTimeoutTimer];
    [[UTEBluetoothMgr sharedInstance] stopScanDevices];
    self.fromQrcode = false;
    
    NSMutableArray *deviceList = [[NSMutableArray alloc] init];
    for (UTEModelDevice *device in self.deviceArray) {
        NSString* addr = device.advertisementAddress;
        if (addr == nil) {
            continue;
        }
        addr = [[StringUtils insertStringAll:addr insertStr:@":" position:2] uppercaseString];
        NSDictionary* deviceDict = [[NSDictionary alloc] initWithObjectsAndKeys:device.name, KEY_NAME, addr, KEY_ADDRESS, nil];
        [deviceList addObject:deviceDict];
    }
    
    NSDictionary* data = [[NSDictionary alloc] initWithObjectsAndKeys:PATH, KEY_PATH, M_scanDevice, KEY_METHOD, TYPE_LIST, KEY_TYPE, deviceList, KEY_LIST, nil];
    [self.eventHander publishEvent: data async:YES];
}

#pragma mark - DeviceOption

- (void)notifyConnected
{
    [self log:[NSString stringWithFormat:@"device is paired: %i", [UTEBluetoothMgr sharedInstance].connnectModel.isPair]];
    __weak typeof(self)weakSelf = self;
    [self syncTimeClock:^(NSInteger errorCode, NSDictionary * _Nonnull uteDict) {
        if (errorCode == UTEDeviceErrorNil) {
            [weakSelf log:@"sync time success"];
        }
    }];
    [self.eventHander publishEvent: [NSDictionary dictionaryWithObjectsAndKeys:
                                      PATH, KEY_PATH,
                                      M_connect, KEY_METHOD,
                                      @(STATE_CONNECTED), KEY_STATUS,
                                      @(weakSelf.isPaired), KEY_PAIRED,
                                      self.address, KEY_ADDRESS, nil] async:YES];
}

- (BOOL)connectDevice
{
    BOOL success = false;
    NSString *tempAddress = [[self.address stringByReplacingOccurrencesOfString:@":" withString:@""] lowercaseString];
    UTEModelDevice* device = [self getDeviceModel: tempAddress];
    if (device == nil) {
        NSString* identifier = [[SPHelper shareInstance] getObject:self.address defaultValue:nil];
//        if (identifier == nil) {
//            identifier = [[SPHelper shareInstance] getObject:KEY_IDENTIFIER defaultValue:nil];
//        }
        if (identifier != nil){
            device = [[UTEModelDevice alloc] init];
            device.identifier = identifier;
        }
    }
    
    if (device != nil) {
        self.currentModel = device;
        [[UTEBluetoothMgr sharedInstance] connectDevice:device];
        success = YES;
    }
    
    return success;
}

- (void)pairDevice
{
    [self log: @"pairDevice"];
    __weak typeof(self)weakSelf = self;
    [[UTEDeviceMgr sharedInstance].accountTool notifyDevicePair:YES block:^(BOOL blePair, NSInteger errorCode) {
        [weakSelf log: [NSString stringWithFormat:@"notifyDevicePair blePair:%i errorCode: %ld", blePair, errorCode]];
        if (errorCode == UTEDeviceErrorNil) {
            weakSelf.isPaired = blePair;
            [[SPHelper shareInstance] putObject:KEY_PAIRED value:@(blePair)];
        }
    }];
}

- (UTEModelDevice*) getDeviceModel:(NSString*) address
{
    for (UTEModelDevice *device in self.deviceArray) {
        if ([device.advertisementAddress isEqualToString:address]) {
            return device;
        }
    }
    
    return nil;
}

- (BOOL)isValidDevice:(UTEModelDevice*) device
{
    if (!device.name) {
        return NO;
    }
    NSString* deviceName = device.name;
    NSNumber *enableFilter = [[SPHelper shareInstance] getObject:M_setDeviceFilter defaultValue:@(YES)];
    if (![enableFilter boolValue]) {
        return deviceName.length > 0;
    }
    
    if ([deviceName containsString:@"Callie"] || [deviceName containsString:@"Helio"] || [deviceName containsString:@"MEGA"]  || [deviceName containsString:@"Vibe Fit"]) {
        return YES;
    }
    
    return NO;
}


#pragma mark - UTEBluetoothDelegate
- (void)uteDiscoverDevices:(UTEModelDevice *)model
{
    if (![self isValidDevice:model]) {
        return;
    }
     
    BOOL isExist = NO;
    for (UTEModelDevice *device in self.deviceArray) {
        if ([device.identifier isEqualToString:model.identifier]) {
            isExist = YES;
            device.rssi = model.rssi;
            device.advertisementAddress = model.advertisementAddress;
            break;
        }
    }
    
    if (!isExist) {
        [self.deviceArray addObject:model];
    }
    
    if (self.fromQrcode) {
        __weak typeof(self)weakSelf = self;
        NSString *tempAddress = [[self.address stringByReplacingOccurrencesOfString:@":" withString:@""] lowercaseString];
        if ([tempAddress isEqualToString:model.advertisementAddress]) {
            [self removeTimeoutTimer];
            [[UTEBluetoothMgr sharedInstance] stopScanDevices];
            
            dispatch_async(dispatch_get_main_queue(), ^{
                [weakSelf connectDevice];
            });
        }
    }
}

- (void)uteBluetoothStatus:(UTEBluetoothStatus)status
{
    if (status != UTEBluetoothStatusOpen) {
//        [self.arrayCell removeAllObjects];
//        dispatch_async(dispatch_get_main_queue(), ^{
//            [self.tableView reloadData];
//        });
    }
}

- (void)uteDevicesStatus:(UTEDevicesStatus)status error:(NSError *)error userInfo:(NSDictionary *)info
{
    __weak typeof(self)weakSelf = self;
    if (status == UTEDevicesStatusConnected) {

        [[SPHelper shareInstance] putObject:KEY_IDENTIFIER value:weakSelf.currentModel.identifier];
        
        if (self.userId == nil) {
            self.userId = [[SPHelper shareInstance] getObject:KEY_USERID defaultValue:@""];
        }
        
        //账号id 要保证唯一性
        [[UTEDeviceMgr sharedInstance].accountTool phoneSendWatchAccountWith:self.userId block:^(NSInteger result, NSInteger errorCode, NSDictionary *uteDict) {
            //0:帐号一致 1:帐号不一致 2:无帐号
//            如果账号一致或者无账号，则通过连接
            NSLog(@"phoneSendWatchAccountWith errorCode = %ld result=%ld",errorCode,result);
            if (errorCode == UTEDeviceErrorNil) {
                if ((result == 0 || result == 2)) {
//                    NSNumber *paired = [[SPHelper shareInstance] getObject:KEY_PAIRED defaultValue:@(NO)];
//                    if ([paired boolValue]) {
//
//                    }
//                    else {
//                        [weakSelf pairDevice];
//                    }
                    [[SPHelper shareInstance] putObject:weakSelf.address value: weakSelf.currentModel.identifier];
                    [[SPHelper shareInstance] putObject:KEY_ADDRESS value: weakSelf.address];
                    dispatch_async(dispatch_get_main_queue(), ^{
                        [weakSelf notifyConnected];
                        [[DeviceHelper shareInstance] onDeviceConnected:weakSelf.address];
                        [weakSelf syncTimeClock:^(NSInteger errorCode, NSDictionary * _Nonnull uteDict) {
                        }];
                        
                        [[UTEDeviceMgr sharedInstance] setTimeDisplay:1 timeType:[weakSelf getTimeDisplay] block:^(NSInteger errorCode, NSDictionary *uteDict) {
                        }];
                    });
                    
                    NSNumber *paired = [[SPHelper shareInstance] getObject:KEY_PAIRED defaultValue:@(NO)];
                    if (![paired boolValue]) {
                        NSTimeInterval bt3PairID = [DateUtils getNowTimeInSeconds];
                        [[UTEDeviceMgr sharedInstance] setBT3Pair:bt3PairID Block:^(NSInteger errorCode) {
                            if(errorCode == UTEDeviceErrorNil){
                                [self log:@"开启BT3.0配对成功"];
                               //然后再调用
                               //Then call again
                                [[SPHelper shareInstance] putObject:KEY_PAIRED value:@(YES)];
                                [[SPHelper shareInstance] putObject:KEY_PAIRID value:@(bt3PairID)];
                                [[UTEDeviceMgr sharedInstance] setBT3Info:1 Block:nil];
                                
                            }else{
                                [self log:@"开启BT3.0配对失败"];
                                [[SPHelper shareInstance] putObject:KEY_PAIRED value:@(NO)];
                            }
                        }];
                    }
                }
                else {
                    if (result == 1 && weakSelf.fromQrcode) {
                        dispatch_async(dispatch_get_main_queue(), ^{
                            [weakSelf performSelector:@selector(connectDevice) withObject:nil afterDelay:7.0];
                        });
                    }
                    else {
                        weakSelf.disconnectType = DISCONNECT_TYPE_ID_CHANGE;
                    }
                }
            }
        }];
        //通过60.4监听 账号不一致ble操作
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf removeTimeoutTimer];
        });
    }
    else if (status == UTEDevicesStatusDisconnected) {
        dispatch_async(dispatch_get_main_queue(), ^{
            
            [weakSelf notifyDisconnectEvent:weakSelf.disconnectType];
            
            if (weakSelf.disconnectType != DISCONNECT_TYPE_NONE) {
//                [[SPHelper shareInstance] removeObject:self.address];
                [[SPHelper shareInstance] removeObject:KEY_ADDRESS];
                weakSelf.address = nil;
            }
            
            weakSelf.disconnectType = DISCONNECT_TYPE_NONE;
        });
    }
    else if (status == UTEDevicesStatusConnectCheckFail) {
        [self log:@"配对失败"];
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf removeTimeoutTimer];
        });
    }
}

-(void)disconnectDevice:(NSInteger) type{
    self.disconnectType = type;
    if (self.disconnectType != DISCONNECT_TYPE_NONE) {
        [[DeviceHelper shareInstance] canelCheckTimer];
    }
    if ([UTEBluetoothMgr sharedInstance].connnectModel.isConnected) {
        [[UTEBluetoothMgr sharedInstance] disconnectDevices:self.currentModel];
    }
    
    if (type == DISCONNECT_TYPE_MANUAL || type == DISCONNECT_TYPE_RESET) {
        [[DeviceHelper shareInstance] onDeviceDisconnect:self.address];
    }
    
    if (type == DISCONNECT_TYPE_MANUAL) {
        [[UTEDeviceMgr sharedInstance].accountTool UnboundType:1 Block:^(NSInteger errorCode, NSDictionary *uteDict) {
            [self log: [NSString stringWithFormat:@"UnboundType errorCode: %ld", errorCode]];
            if (errorCode == UTEDeviceErrorNil) {
                
            }
        }];
    }
}

-(void)notifyDisconnectEvent:(NSInteger) type {
    NSDictionary *data = [[NSDictionary alloc] initWithObjectsAndKeys:
                          PATH, KEY_PATH,
                          M_disconnect, KEY_METHOD,
                          @(type), KEY_TYPE,
                          @(STATE_DISCONNECTED), KEY_STATUS,
                          self.address, KEY_ADDRESS, nil];

    [self.eventHander publishEvent:data async:YES];
}

//响铃回调方法
void soundCompleteCallback(SystemSoundID sound, void * clientData) {
    AudioServicesPlaySystemSound(sound);
}

@end
